package com.zlsoft.web.ui.activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.google.zxing.client.android.Intents;
import com.huawei.hms.hmsscankit.ScanUtil;
import com.huawei.hms.ml.scan.HmsScan;
import com.journeyapps.barcodescanner.ScanContract;
import com.journeyapps.barcodescanner.ScanOptions;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnConfirmListener;
import com.qqz.common.utils.DoubleClickHelper;
import com.qqz.common.utils.activity.ActivityManager;
import com.tencent.smtt.export.external.interfaces.JsPromptResult;
import com.tencent.smtt.export.external.interfaces.JsResult;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
import com.zenglb.downloadinstaller.DownloadProgressCallBack;
import com.zlsoft.mobilenurse.R;
import com.zlsoft.web.AndroidInterface;
import com.zlsoft.web.AnyOrientationCaptureActivity;
import com.zlsoft.web.base.BaseActivity;
import com.zlsoft.web.config.WebViewBaseConfig;
import com.zlsoft.web.constant.DynamicValue;
import com.zlsoft.web.sp.ConfigPreference;
import com.zlsoft.web.utils.QrUtils;
import com.zlsoft.web.utils.UpdateManager;
import com.zlsoft.web.utils.X5WebView;
import com.zlsoft.web.utils.permissions.PermissionsUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import me.zhanghai.android.materialprogressbar.MaterialProgressBar;

/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 */
public class MainActivity extends BaseActivity implements DownloadProgressCallBack {

    private X5WebView mX5WebView;

    private final static int FILE_CHOOSER_RESULT_CODE = 1;

    private final static int FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5 = 2;

    private ValueCallback<Uri[]> mUploadMessageForAndroid5;

    private ValueCallback<Uri> mUploadMessage;

    private String mCurrentUrl;

    /**
     * 加载进度
     */
    private MaterialProgressBar mMpbLoadingProgress;
    /**
     * 错误布局
     */
    private ViewGroup mVgErrorLayout;

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebViewBaseConfig.getBaseConfig().initHardwareAccelerate(this);
        initView();

        if (mX5WebView != null) {
            mX5WebView.addJavascriptInterface(new AndroidInterface(this, mX5WebView, barcodeLauncher), "myInterfaceName");
            mX5WebView.setDownloadListener((url, mS1, mS2, mS3, mL) -> {
                Uri uri = Uri.parse(url);
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(intent);
            });

            mX5WebView.loadUrl(DynamicValue.getWebPath());
        }
        UpdateManager.checkVersion(this);

        WebView.setWebContentsDebuggingEnabled(true);

    }


    /**
     * 初始化控件
     */
    private void initView() {
        mVgErrorLayout = findViewById(R.id.vg_web_view_error_container);
        // 重试
        mVgErrorLayout.findViewById(R.id.tv_web_view_error_retry).setOnClickListener(v -> loadLastFailingUrl());
        // 更换地址
        mVgErrorLayout.findViewById(R.id.tv_web_view_change_url).setOnClickListener(v -> {
            try {
                ConfigPreference.getInstance().setConfig("");
            } catch (IOException mE) {
                mE.printStackTrace();
            }

            QrUtils.getInstance().QrProduct(this, QrUtils.HW_SCAN_FOR_RESULT_LOCAL_CODE);
        });

        // 进度条
        mMpbLoadingProgress = (MaterialProgressBar) findViewById(R.id.mpb_web_view_progress);
        mMpbLoadingProgress.bringToFront();

        // web view
        mX5WebView = findViewById(R.id.fullscreen_content);

        mX5WebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView webView, String s, String s1, JsResult jsResult) {
                return super.onJsAlert(webView, s, s1, jsResult);
            }

            @Override
            public boolean onJsConfirm(WebView webView, String s, String s1, JsResult jsResult) {
                return super.onJsConfirm(webView, s, s1, jsResult);
            }

            @Override
            public boolean onJsPrompt(WebView webView, String s, String s1, String s2, JsPromptResult jsPromptResult) {
                return super.onJsPrompt(webView, s, s1, s2, jsPromptResult);
            }

            @Override
            public void onProgressChanged(WebView mWebView, int newProgress) {
                super.onProgressChanged(mWebView, newProgress);
                if (newProgress == 100) {
                    mMpbLoadingProgress.setVisibility(View.GONE);
                } else {
                    if (mMpbLoadingProgress.getVisibility() == View.GONE) {
                        mMpbLoadingProgress.setVisibility(View.VISIBLE);
                    }
                    if (newProgress == 0) {
                        newProgress = 5;
                    }
                    mMpbLoadingProgress.setProgress(newProgress);
                }
            }

            //扩展浏览器上传文件
            //3.0++版本
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                openFileChooserImpl(uploadMsg);
            }

            //3.0--版本
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                openFileChooserImpl(uploadMsg);
            }

            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                openFileChooserImpl(uploadMsg);
            }

            // For Android > 5.0
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> uploadMsg, FileChooserParams fileChooserParams) {
                openFileChooserImplForAndroid5(uploadMsg, fileChooserParams);
                return true;
            }

        });

        mX5WebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                mMpbLoadingProgress.setVisibility(View.GONE);
                mCurrentUrl = url;
                super.onPageFinished(view, url);

            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String s) {
                if (WebViewBaseConfig.getBaseConfig().processShouldOverrideUrlLoading(MainActivity.this, s) == 0) {
                    webView.loadUrl(s);
                }
                return true;
            }

            @Override
            public void onReceivedError(WebView mWebView, int mI, String mS, String mS1) {
                super.onReceivedError(mWebView, mI, mS, mS1);
                showErrorPage(mS);
            }

            @Override
            public void onPageStarted(WebView mWebView, String mS, Bitmap mBitmap) {
                super.onPageStarted(mWebView, mS, mBitmap);
                hideErrorPage();
            }
        });
    }

    private void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg, WebChromeClient.FileChooserParams mFileChooserParams) {
        PermissionsUtils.getInstance().getPermission(MainActivity.this, mB -> {
            if (mB) {
                mUploadMessageForAndroid5 = uploadMsg;

                String optionType = "image/*";
                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                if (mFileChooserParams.isCaptureEnabled()) {

                    chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    optionType = "image/jpeg";
                }

                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType(optionType);

                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
                startActivityForResult(chooserIntent, FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5);
            } else {

            }
        });
    }


    private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) {
        mUploadMessage = uploadMsg;
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_RESULT_CODE);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILE_CHOOSER_RESULT_CODE) {
            if (null == mUploadMessage) {
                return;
            }
            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
            if (null == result) {
                mUploadMessage.onReceiveValue(null);
                return;
            }
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;

        } else if (requestCode == FILE_CHOOSER_RESULT_CODE_FOR_ANDROID_5) {
            if (null == mUploadMessageForAndroid5) {
                return;
            }
            Uri result = (data == null || resultCode != RESULT_OK) ? null : data.getData();


            if (result != null) {
                mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});

            } else {

                if (null != data && null != data.getExtras()) {
                    Bundle mExtras = data.getExtras();
                    Bitmap bitmap = (Bitmap) mExtras.get("data");
                    result = Uri.parse(MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, null, null));
                }
                if (null == result) {
                    mUploadMessageForAndroid5.onReceiveValue(null);
                    return;
                }
                mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});
            }
            mUploadMessageForAndroid5 = null;
        }

        // 本地配置、网页配置
        if (requestCode == QrUtils.HW_SCAN_FOR_RESULT_LOCAL_CODE || requestCode == QrUtils.HW_SCAN_FOR_REST_WEB_RESULT_WEB_CODE) {
            HmsScan obj = null;
            try {
                obj = data.getParcelableExtra(ScanUtil.RESULT);
            } catch (Exception e) {
                Toast.makeText(mActivity, "请重新尝试", Toast.LENGTH_SHORT).show();
            }
            if (null != obj) {

                String result = obj.originalValue;
                if (!result.contains("http")) {
                    Toast.makeText(mActivity, "该二维码不包含正确的地址信息.", Toast.LENGTH_LONG).show();
                    new XPopup.Builder(mActivity).asConfirm("提示", "不是正确的一个地址,是否重新尝试?", () -> {
                        ScanOptions options = new ScanOptions();
                        options.setCaptureActivity(AnyOrientationCaptureActivity.class);
                        barcodeLauncher.launch(options);
                    }).show();
                    return;
                }

                try {
                    ConfigPreference.getInstance().setConfig(result);
                    Toast.makeText(mActivity, "配置成功", Toast.LENGTH_LONG).show();
                    mX5WebView.loadUrl(DynamicValue.getWebPath());

                } catch (Exception e) {
                    Toast.makeText(mActivity, "配置失败,请参考帮助手册", Toast.LENGTH_SHORT).show();
                }
            }
        }

        if (requestCode == QrUtils.HW_SCAN_FOR_RESULT_WEB_CODE) {
            if (null != data) {
                HmsScan mHmsScan = data.getParcelableExtra(ScanUtil.RESULT);
                if (null != mHmsScan) {
                    try {
                        ConfigPreference.getInstance().setConfig(mHmsScan.originalValue);
                    } catch (IOException mE) {
                        Log.e("MainActivity", "IOException occurred while setting config", mE);
                    }
                    mX5WebView.evaluateJavascript("scanQRCallBack('" + mHmsScan.originalValue + "')", null);
                }
            }
        }

    }

    /**
     * 加载上次失败的Url
     */
    private void loadLastFailingUrl() {
        if (mX5WebView == null) {

            return;
        }

        mMpbLoadingProgress.setProgress(5);

        mX5WebView.reload();
    }

    /**
     * 显示错误页面
     *
     * @param reason 错误原因
     */
    private void showErrorPage(String reason) {
        // 标记已经出现错误
//        mIsError = true;

        // 显示错误
        TextView tvReason = mVgErrorLayout.findViewById(R.id.tv_web_view_error_reason);
        if (!TextUtils.isEmpty(reason)) {
            tvReason.setText("(" + reason + ")");
        } else {
            tvReason.setText("reason");
        }
        mVgErrorLayout.setVisibility(View.VISIBLE);
    }

    public void quickCallJs(String method, android.webkit.ValueCallback<String> callback, String... params) {

        StringBuilder sb = new StringBuilder();
        sb.append("javascript:" + method);
        if (params == null || params.length == 0) {
            sb.append("()");
        } else {
            sb.append("(").append(concat(params)).append(")");
        }


        callJs(sb.toString(), callback);

    }

    public void callJs(String js, final android.webkit.ValueCallback<String> callback) {

        Log.i("Info", "js:" + js);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            this.evaluateJs(js, callback);
        } else {
            mX5WebView.loadUrl(js);
        }

    }

    private void evaluateJs(String js, final android.webkit.ValueCallback<String> callback) {

        mX5WebView.evaluateJavascript(js, new com.tencent.smtt.sdk.ValueCallback<String>() {
            @Override
            public void onReceiveValue(String value) {
                if (callback != null)
                    callback.onReceiveValue(value);
            }
        });
    }

    private String concat(String... params) {

        StringBuilder mStringBuilder = new StringBuilder();

        for (int i = 0; i < params.length; i++) {
            String param = params[i];
            if (!isJson(param)) {

                mStringBuilder.append("\"").append(param).append("\"");
            } else {
                mStringBuilder.append(param);
            }

            if (i != params.length - 1) {
                mStringBuilder.append(" , ");
            }

        }

        return mStringBuilder.toString();
    }

    public static boolean isJson(String target) {
        if (TextUtils.isEmpty(target))
            return false;

        boolean tag = false;
        try {
            if (target.startsWith("["))
                new JSONArray(target);
            else
                new JSONObject(target);

            tag = true;
        } catch (JSONException igonre) {
//            igonre.printStackTrace();
            tag = false;
        }

        return tag;

    }

    /**
     * 隐藏错误页面
     */
    private void hideErrorPage() {
        if (mX5WebView == null) {

            return;
        }

        mVgErrorLayout.setVisibility(View.INVISIBLE);
    }

    private final ActivityResultLauncher<ScanOptions> barcodeLauncher = registerForActivityResult(new ScanContract(),
            result -> {
                if (result.getContents() == null) {

                    Intent originalIntent = result.getOriginalIntent();
                    if (originalIntent == null) {
                        Toast.makeText(MainActivity.this, "取消扫描", Toast.LENGTH_LONG).show();
                    } else if (originalIntent.hasExtra(Intents.Scan.MISSING_CAMERA_PERMISSION)) {
                        Toast.makeText(MainActivity.this, "缺少相机权限", Toast.LENGTH_LONG).show();
                    }

                } else {

                    String contents = result.getContents();

                    if (result.getFormatName().equals("QR_CODE")) {
                        if (!contents.contains("http")) {
                            Toast.makeText(mActivity, "该二维码不包含正确的地址信息.", Toast.LENGTH_LONG).show();
                            new XPopup.Builder(mActivity).asConfirm("提示", "不是正确的一个地址,是否重新尝试?", new OnConfirmListener() {
                                @Override
                                public void onConfirm() {
                                    ScanOptions options = new ScanOptions();
                                    options.setCaptureActivity(AnyOrientationCaptureActivity.class);
                                    barcodeLauncher.launch(options);
                                }
                            }).show();
                            return;
                        }
                        // 二维码
                        try {
                            ConfigPreference.getInstance().setConfig(contents);
                        } catch (IOException mE) {
                            mE.printStackTrace();
                        }

                        mX5WebView.loadUrl(DynamicValue.getWebPath());
                        Toast.makeText(mActivity, "配置成功", Toast.LENGTH_LONG).show();
                    } else {
                        // 条形码数据
                        mX5WebView.evaluateJavascript("javascript:scanQRCallBack('" + contents + "')", null);
                    }
                }
            });

    @Override
    public void onBackPressed() {
        if (!DoubleClickHelper.isOnDoubleClick()) {
            Toast.makeText(mActivity, "再按一次退出程序", Toast.LENGTH_SHORT).show();
            return;
        }
        moveTaskToBack(false);
        new Handler().postDelayed(() -> {
            ActivityManager.getInstance().finishAllActivities();
        }, 300);
    }

    @Override
    public void downloadProgress(int progress) {

    }

    @Override
    public void downloadException(Exception e) {

    }

    @Override
    public void onInstallStart() {

    }
}